using System;
using System.Collections.Generic;
using System.Text;

namespace Placid.Core
{
    public class PTreeNode : IEnumerable<PTreeNode>, IDisposable, IComparable<PTreeNode>
    {
        private PTreeNode _parent;
        private Dictionary<string, PTreeNode> _childrenByName;
        private List<PTreeNode> _children;
        private string _name;
        private object _value;

        public PTreeNode(string name)
            : this(name, null)
        {
        }

        public PTreeNode(string name, PTreeNode parent)
        {
            _name = name;
            _parent = parent;
            _children = new List<PTreeNode>();
            _childrenByName = new Dictionary<string, PTreeNode>();
            _value = null;
        }

        public bool AddNode(PTreeNode ptn)
        {
            if (ptn != null && !_children.Contains(ptn) && !_childrenByName.ContainsKey(ptn.Name))
            {
                _children.Add(ptn);
                _childrenByName.Add(ptn.Name, ptn);

                if (ptn._parent != null) ptn._parent.RemoveNode(ptn);
                ptn._parent = this;

                return true;
            }
            return false;
        }

        public void RemoveNode(PTreeNode pTreeNode)
        {
            if (_children.Contains(pTreeNode))
            {
                _children.Remove(pTreeNode);
                _childrenByName.Remove(pTreeNode.Name);
            }
        }

        public void Clear()
        {
            foreach (PTreeNode ptn in _children)
            {
                ptn.Clear();
            }

            _children.Clear();
            _childrenByName.Clear();
            _value = null;
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public bool IsRoot
        {
            get
            {
                return _parent == null;
            }
        }

        public PTreeNode this[int index]
        {
            get
            {
                if (index >= 0 && _children != null && _children.Count > index)
                {
                    return _children[index];
                }
                else
                {
                    return null;
                }
            }
        }

        public PTreeNode this[string name]
        {
            get
            {
                if (_childrenByName != null && _childrenByName.ContainsKey(name))
                {
                    return _childrenByName[name];
                }
                else
                {
                    return null;
                }
            }
        }

        public PTreeNode Parent
        {
            get { return _parent; }
        }

        public List<PTreeNode> Children
        {
            get { return _children; }
        }

        public List<PTreeNode> Siblings
        {
            get
            {
                if (_parent != null)
                {
                    List<PTreeNode> siblings = new List<PTreeNode>();
                    foreach (PTreeNode ptn in _parent)
                    {
                        if (ptn != this)
                        {
                            siblings.Add(ptn);
                        }
                    }
                    return siblings;
                }
                return null;
            }
        }

        public int Depth
        {
            get
            {
                if (_children != null && _children.Count > 0)
                {
                    return _children[0].Depth + 1;
                }
                else
                {
                    return 1;
                }
            }
        }

        public string Path
        {
            get
            {
                string str = "";
                if (_parent != null) str += _parent.Path;
                return str + "/" + _name;
            }
        }

        public object Value
        {
            get { return _value; }
            set { _value = value; }
        }

        public string ValueString(string separator)
        {
            string str;

            if (_parent != null)
            {
                str = _parent.ValueString(separator) + separator;
                if (_value != null)
                {
                    str += _value.ToString();
                }
                else
                {
                    str += "[null]";
                }
            }
            else str = "";

            return str;
        }

        public override string ToString()
        {
            return Path;
        }

        #region IEnumerable<PTreeNode> Members

        public IEnumerator<PTreeNode> GetEnumerator()
        {
            return _children.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _children.GetEnumerator();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            foreach (PTreeNode ptn in _children) ptn.Dispose();
            Clear();
            _parent = null;
        }

        #endregion

        #region IComparable<PTreeNode> Members

        public int CompareTo(PTreeNode other)
        {
            if (other == null) return 1;
            else return this.Path.CompareTo(other.Path);
        }

        #endregion
    }
}
